-- Generated from template

if SanGuoXueGameMode == nil then
	_G.SanGuoXueGameMode = class({})
end
--require('gamemode')
require('utilities')
require('upgrades')
require('mechanics')
require('orders')
require('builder')
require('buildinghelper')

require('libraries/timers')
require('libraries/popups')
require('libraries/notifications')

require('TableSet/modeltable')
require('System/AttacktypeAndDefensetype')
require('settings')

function Precache( context )
	--[[
		Precache things we know we'll use.  Possible file types include (but not limited to):
			PrecacheResource( "model", "*.vmdl", context )
			PrecacheResource( "soundfile", "*.vsndevts", context )
			PrecacheResource( "particle", "*.vpcf", context )
			PrecacheResource( "particle_folder", "particles/folder", context )
	]]
	PrecacheResource("particle_folder", "particles/buildinghelper", context)
	PrecacheResource("particle_folder", "particles/econ/items/earthshaker/earthshaker_gravelmaw/", context)

	-- Resources used
	PrecacheUnitByNameSync("peasant", context)
	PrecacheUnitByNameSync("tower", context)
	PrecacheUnitByNameSync("tower_tier2", context)
	PrecacheUnitByNameSync("city_center", context)
	PrecacheUnitByNameSync("city_center_tier2", context)
	PrecacheUnitByNameSync("tech_center", context)
	PrecacheUnitByNameSync("dragon_tower", context)
	PrecacheUnitByNameSync("dark_tower", context)
	PrecacheUnitByNameSync("wall", context)
	PrecacheResource( "model", "models/question_mark/question_mark.vmdl", context )
	PrecacheItemByNameSync("item_apply_modifiers", context)

	--载入模型
	for i = 1,#modeltable do
		PrecacheResource( "model", modeltable[i], context )
	end

end

-- Create the game mode when we activate
function Activate()
	GameRules.AddonTemplate = SanGuoXueGameMode()
	GameRules.AddonTemplate:InitGameMode()
end

function SanGuoXueGameMode:InitGameMode()
	print( "Template addon is loaded." )
	GameRules.SGX_PLAYER_COUNT = 8
	GameRules:GetGameModeEntity():SetThink( "OnThink", self, "GlobalThink", 2 )

	----------------------------------
	--以下为barebones里的setting部分--
	----------------------------------
		GameRules:SetHeroRespawnEnabled( ENABLE_HERO_RESPAWN )
		GameRules:SetUseUniversalShopMode( UNIVERSAL_SHOP_MODE )
		GameRules:SetSameHeroSelectionEnabled( ALLOW_SAME_HERO_SELECTION )
		GameRules:SetHeroSelectionTime( HERO_SELECTION_TIME )
		GameRules:SetPreGameTime( PRE_GAME_TIME)
		GameRules:SetPostGameTime( POST_GAME_TIME )
		GameRules:SetTreeRegrowTime( TREE_REGROW_TIME )
		GameRules:SetUseCustomHeroXPValues ( USE_CUSTOM_XP_VALUES )
		GameRules:SetGoldPerTick(GOLD_PER_TICK)
		GameRules:SetGoldTickTime(GOLD_TICK_TIME)
		GameRules:SetRuneSpawnTime(RUNE_SPAWN_TIME)
		GameRules:SetUseBaseGoldBountyOnHeroes(USE_STANDARD_HERO_GOLD_BOUNTY)
		GameRules:SetHeroMinimapIconScale( MINIMAP_ICON_SIZE )
		GameRules:SetCreepMinimapIconScale( MINIMAP_CREEP_ICON_SIZE )
		GameRules:SetRuneMinimapIconScale( MINIMAP_RUNE_ICON_SIZE )
		GameRules:SetFirstBloodActive( ENABLE_FIRST_BLOOD )
		GameRules:SetHideKillMessageHeaders( HIDE_KILL_BANNERS )

		-- This is multiteam configuration stuff
		if USE_AUTOMATIC_PLAYERS_PER_TEAM then
			local num = math.floor(10 / MAX_NUMBER_OF_TEAMS)
			local count = 0
			for team,number in pairs(TEAM_COLORS) do
				if count >= MAX_NUMBER_OF_TEAMS then
					GameRules:SetCustomGameTeamMaxPlayers(team, 0)
				else
					GameRules:SetCustomGameTeamMaxPlayers(team, num)
				end
				count = count + 1
	    	end
		else
			local count = 0
			for team,number in pairs(CUSTOM_TEAM_PLAYER_COUNT) do
				if count >= MAX_NUMBER_OF_TEAMS then
					GameRules:SetCustomGameTeamMaxPlayers(team, 0)
				else
					GameRules:SetCustomGameTeamMaxPlayers(team, number)
				end
				count = count + 1
			end
		end

		if USE_CUSTOM_TEAM_COLORS then
			for team,color in pairs(TEAM_COLORS) do
				SetTeamCustomHealthbarColor(team, color[1], color[2], color[3])
			end
		end

		-- Change random seed
		local timeTxt = string.gsub(string.gsub(GetSystemTime(), ':', ''), '0','')
		math.randomseed(tonumber(timeTxt))

		-- Initialized tables for tracking state
		self.bSeenWaitForPlayers = false

		mode = nil

		if mode == nil then
			-- Set GameMode parameters
			mode = GameRules:GetGameModeEntity()        
			mode:SetRecommendedItemsDisabled( RECOMMENDED_BUILDS_DISABLED )
			mode:SetCameraDistanceOverride( CAMERA_DISTANCE_OVERRIDE )
			mode:SetCustomBuybackCostEnabled( CUSTOM_BUYBACK_COST_ENABLED )
			mode:SetCustomBuybackCooldownEnabled( CUSTOM_BUYBACK_COOLDOWN_ENABLED )
			mode:SetBuybackEnabled( BUYBACK_ENABLED )
			mode:SetTopBarTeamValuesOverride ( USE_CUSTOM_TOP_BAR_VALUES )
			mode:SetTopBarTeamValuesVisible( TOP_BAR_VISIBLE )
			mode:SetUseCustomHeroLevels ( USE_CUSTOM_HERO_LEVELS )
			mode:SetCustomHeroMaxLevel ( MAX_LEVEL )
			mode:SetCustomXPRequiredToReachNextLevel( XP_PER_LEVEL_TABLE )

			mode:SetBotThinkingEnabled( USE_STANDARD_DOTA_BOT_THINKING )
			mode:SetTowerBackdoorProtectionEnabled( ENABLE_TOWER_BACKDOOR_PROTECTION )

			mode:SetFogOfWarDisabled(DISABLE_FOG_OF_WAR_ENTIRELY)
			mode:SetGoldSoundDisabled( DISABLE_GOLD_SOUNDS )
			mode:SetRemoveIllusionsOnDeath( REMOVE_ILLUSIONS_ON_DEATH )

			mode:SetAlwaysShowPlayerInventory( SHOW_ONLY_PLAYER_INVENTORY )
			mode:SetAnnouncerDisabled( DISABLE_ANNOUNCER )
			if FORCE_PICKED_HERO ~= nil then
				mode:SetCustomGameForceHero( FORCE_PICKED_HERO )
			end
			mode:SetFixedRespawnTime( FIXED_RESPAWN_TIME ) 
			mode:SetFountainConstantManaRegen( FOUNTAIN_CONSTANT_MANA_REGEN )
			mode:SetFountainPercentageHealthRegen( FOUNTAIN_PERCENTAGE_HEALTH_REGEN )
			mode:SetFountainPercentageManaRegen( FOUNTAIN_PERCENTAGE_MANA_REGEN )
			mode:SetLoseGoldOnDeath( LOSE_GOLD_ON_DEATH )
			mode:SetMaximumAttackSpeed( MAXIMUM_ATTACK_SPEED )
			mode:SetMinimumAttackSpeed( MINIMUM_ATTACK_SPEED )
			mode:SetStashPurchasingDisabled ( DISABLE_STASH_PURCHASING )

			for rune, spawn in pairs(ENABLED_RUNES) do
				mode:SetRuneEnabled(rune, spawn)
			end

			mode:SetUnseenFogOfWarEnabled(USE_UNSEEN_FOG_OF_WAR)

			--self:OnFirstPlayerLoaded()
		end
	----------------------------------
	--以上为barebones里的setting部分--
	----------------------------------

	--BH
	-- Get Rid of Shop button - Change the UI Layout if you want a shop button
	GameRules:GetGameModeEntity():SetHUDVisible(6, false)
	GameRules:GetGameModeEntity():SetCameraDistanceOverride(1300)

	-- DebugPrint
	Convars:RegisterConvar('debug_spew', tostring(DEBUG_SPEW), 'Set to 1 to start spewing debug info. Set to 0 to disable.', 0)
	
	-- Event Hooks
	ListenToGameEvent('entity_killed', Dynamic_Wrap(SanGuoXueGameMode, 'OnEntityKilled'), self)
	ListenToGameEvent('dota_player_pick_hero', Dynamic_Wrap(SanGuoXueGameMode, 'OnPlayerPickHero'), self)
	ListenToGameEvent( "game_rules_state_change", Dynamic_Wrap( SanGuoXueGameMode, 'OnGameRulesStateChange' ), self )
	-- Filters
    GameRules:GetGameModeEntity():SetExecuteOrderFilter( Dynamic_Wrap( SanGuoXueGameMode, "FilterExecuteOrder" ), self )
    GameRules:GetGameModeEntity():SetDamageFilter( Dynamic_Wrap( SanGuoXueGameMode, "FilterDamage" ), self )

    -- Register Listener
    CustomGameEventManager:RegisterListener( "update_selected_entities", Dynamic_Wrap(SanGuoXueGameMode, 'OnPlayerSelectedEntities'))
   	CustomGameEventManager:RegisterListener( "repair_order", Dynamic_Wrap(SanGuoXueGameMode, "RepairOrder"))  	
    CustomGameEventManager:RegisterListener( "building_helper_build_command", Dynamic_Wrap(BuildingHelper, "BuildCommand"))
	CustomGameEventManager:RegisterListener( "building_helper_cancel_command", Dynamic_Wrap(BuildingHelper, "CancelCommand"))
	
	-- Full units file to get the custom values
	GameRules.AbilityKV = LoadKeyValues("scripts/npc/npc_abilities_custom.txt")
  	GameRules.UnitKV = LoadKeyValues("scripts/npc/npc_units_custom.txt")
  	GameRules.HeroKV = LoadKeyValues("scripts/npc/npc_heroes_custom.txt")
  	GameRules.ItemKV = LoadKeyValues("scripts/npc/npc_items_custom.txt")
  	GameRules.Requirements = LoadKeyValues("scripts/kv/tech_tree.kv")

  	-- Store and update selected units of each pID
	GameRules.SELECTED_UNITS = {}

	-- Keeps the blighted gridnav positions
	GameRules.Blight = {}
end
Inited = false
function SanGuoXueGameMode:OnGameRulesStateChange(event)
	local state = GameRules:State_Get()
	if state == DOTA_GAMERULES_STATE_HERO_SELECTION then
		for i = 0,7 do
			if PlayerResource:IsValidPlayer(i) then
				local hero = CreateHeroForPlayer("npc_dota_hero_wisp",PlayerResource:GetPlayer(i))
			end
		end
	end
end
-- Evaluate the state of the game
function SanGuoXueGameMode:OnThink()
	if GameRules:State_Get() == DOTA_GAMERULES_STATE_GAME_IN_PROGRESS then
	if not Inited then
		resource:init()
		--position_init:init()
		Inited = true
	end
		--print( "Template addon script is running." )
	elseif GameRules:State_Get() >= DOTA_GAMERULES_STATE_POST_GAME then
		return nil
	end
	return 1
end

-- A player picked a hero
function SanGuoXueGameMode:OnPlayerPickHero(keys)

	local hero = EntIndexToHScript(keys.heroindex)
	local player = EntIndexToHScript(keys.player)
	local playerID = hero:GetPlayerID()
	print("playerID: "..playerID)
	player.unit_spawner = {}
	--position_init:init()
	-- Initialize Variables for Tracking
	player.units = {} -- This keeps the handle of all the units of the player, to iterate for unlocking upgrades
	player.structures = {} -- This keeps the handle of the constructed units, to iterate for unlocking upgrades
	player.buildings = {} -- This keeps the name and quantity of each building
	player.upgrades = {} -- This kees the name of all the upgrades researched
	player.lumber = 0 -- Secondary resource of the player
	player.is_clockwise = true
	player.is_alignment = false
	local entity = Entities:FindByName(nil,"PlayerSpawner"..tostring(playerID+1))
	hero:SetOrigin(entity:GetOrigin())
	hero:AddNewModifier(hero, nil, "modifier_invulnerable",{})
    -- Create city center in front of the hero
    player.army_path = "clockwise"
    local position = hero:GetAbsOrigin() + hero:GetForwardVector() * 300
    local city_center_name = "city_center"
	--local building = BuildingHelper:PlaceBuilding(player, city_center_name, position, true, 5) 

	local test_base = Entities:FindByName(nil,"PlayerBaseCamp"..tostring(playerID+1))
	test_base:SetControllableByPlayer(playerID, true)
	test_base:SetOwner(hero)
	-- Set health to test repair
	--building:SetHealth(building:GetMaxHealth()/3)

	-- These are required for repair to know how many resources the building takes
	--building.GoldCost = 100
	--building.LumberCost = 100
	--building.BuildTime = 15

	-- Add the building to the player structures list
	--player.buildings[city_center_name] = 1
	table.insert(player.structures, building)

	CheckAbilityRequirements( hero, player )
	CheckAbilityRequirements( building, player )

	-- Add the hero to the player units list
	table.insert(player.units, hero)
	hero.state = "idle" --Builder state

	-- Spawn some peasants around the hero
	--[[
	local position = hero:GetAbsOrigin()
	local numBuilders = 5
	local angle = 360/numBuilders
	for i=1,5 do
		local rotate_pos = position + Vector(1,0,0) * 100
		local builder_pos = RotatePosition(position, QAngle(0, angle*i, 0), rotate_pos)

		local builder = CreateUnitByName("peasant", builder_pos, true, hero, hero, hero:GetTeamNumber())
		builder:SetOwner(hero)
		builder:SetControllableByPlayer(playerID, true)
		table.insert(player.units, builder)
		builder.state = "idle"

		-- Go through the abilities and upgrade
		CheckAbilityRequirements( builder, player )
	end]]

	-- Give Initial Resources
	hero:SetGold(1525, false)
	ModifyLumber(player, 5000)

	-- Give a building ability
--	local item = CreateItem("item_build_wall", hero, hero)
--	hero:AddItem(item)

	-- Learn all abilities (this isn't necessary on creatures)
	for i=0,15 do
		local ability = hero:GetAbilityByIndex(i)
		if ability then ability:SetLevel(ability:GetMaxLevel()) end
	end
	hero:SetAbilityPoints(0)
	CreateAandDSystem(hero,"hero","hero")

end

-- An entity died
function SanGuoXueGameMode:OnEntityKilled( event )

	-- The Unit that was Killed
	local killedUnit = EntIndexToHScript(event.entindex_killed)
	-- The Killing entity
	local killerEntity
	if event.entindex_attacker then
		killerEntity = EntIndexToHScript(event.entindex_attacker)
	end

	-- Player owner of the unit
	local player = killedUnit:GetPlayerOwner()

	-- Building Killed
	if IsCustomBuilding(killedUnit) then

		 -- Building Helper grid cleanup
		BuildingHelper:RemoveBuilding(killedUnit, true)

		-- Check units for downgrades
		local building_name = killedUnit:GetUnitName()
				
		-- Substract 1 to the player building tracking table for that name
		if player.buildings[building_name] then
			player.buildings[building_name] = player.buildings[building_name] - 1
		end

		-- possible unit downgrades
		for k,units in pairs(player.units) do
		    CheckAbilityRequirements( units, player )
		end

		-- possible structure downgrades
		for k,structure in pairs(player.structures) do
			CheckAbilityRequirements( structure, player )
		end
	end

	-- Cancel queue of a builder when killed
	if IsBuilder(killedUnit) then
		BuildingHelper:ClearQueue(killedUnit)
	end

	-- Table cleanup
	if player then
		-- Remake the tables
		local table_structures = {}
		for _,building in pairs(player.structures) do
			if building and IsValidEntity(building) and building:IsAlive() then
				--print("Valid building: "..building:GetUnitName())
				table.insert(table_structures, building)
			end
		end
		player.structures = table_structures
		
		local table_units = {}
		for _,unit in pairs(player.units) do
			if unit and IsValidEntity(unit) then
				table.insert(table_units, unit)
			end
		end
		player.units = table_units		
	end
end

-- Called whenever a player changes its current selection, it keeps a list of entity indexes
function SanGuoXueGameMode:OnPlayerSelectedEntities( event )
	local pID = event.pID

	GameRules.SELECTED_UNITS[pID] = event.selected_entities

	-- This is for Building Helper to know which is the currently active builder
	local mainSelected = GetMainSelectedEntity(pID)
	if IsValidEntity(mainSelected) and IsBuilder(mainSelected) then
		local player = PlayerResource:GetPlayer(pID)
		player.activeBuilder = mainSelected
	end
end
-- Filter damage
FilterDamageTable = {}
function RegisterDamageFilter( hfunction )
	table.insert(FilterDamageTable,hfunction)
	return hfunction
end
function RemoveDamageFilter( hfunction )
	for i=#FilterDamageTable,1,-1 do
		if FilterDamageTable[i] == hfunction then
			table.remove(FilterDamageTable,i)
		end
	end
end
function SanGuoXueGameMode:FilterDamage( filterTable )
	for i,hfunction in pairs(FilterDamageTable) do
		hfunction( filterTable )
	end
	return true
end
require('System/resource')
--require('System/position_init')